import sys
import time

from alist import AlistClient, AlistCopyTaskList


class CopyRetry(object):
    PRINT_TASKS = False

    MAX_RETRIES = 5

    TASK_WAITING = 0
    TASK_COPYING = 1
    TASK_SUCCESS = 2
    TASK_FAILED = 7
    TASK_WAITING_RETRY = 8

    NOT_FAILED_TASKS = (TASK_WAITING, TASK_COPYING, TASK_SUCCESS, TASK_WAITING_RETRY)

    def __init__(self):
        self.retry_dict = dict()
        self.client = AlistClient("http://192.168.3.200:5244", "admin", "bs0919bs")
        #self.client = AlistClient("http://192.168.100.200:5244", "admin", "bs0919bs")

    @staticmethod
    def println(msg: str):
        print(f'[{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] {msg}')
        sys.stdout.flush()

    def _check(self) -> (bool, bool):
        copy_tasklist: AlistCopyTaskList = self.client.copy_tasklist
        copy_tasklist.clear_succeeded()  # don't care succeeded tasks

        # success_list = list(filter(lambda t: t["state"] == TASK_SUCCESS, copy_tasklist))
        copying_list = list(filter(lambda t: t["state"] == CopyRetry.TASK_COPYING, copy_tasklist))
        waiting_list = list(filter(lambda t: t["state"] == CopyRetry.TASK_WAITING, copy_tasklist))
        waiting_retry_list = list(filter(lambda t: t["state"] == CopyRetry.TASK_WAITING_RETRY, copy_tasklist))
        success_list = list(filter(lambda t: t["state"] == CopyRetry.TASK_SUCCESS, copy_tasklist))
        failed_list = list(filter(lambda t: t["state"] not in CopyRetry.NOT_FAILED_TASKS, copy_tasklist))

        print(f'-----------------------------------')
        CopyRetry.println(f'copying tasks: {len(copying_list)}')
        CopyRetry.println(f'waiting tasks: {len(waiting_list)}')
        CopyRetry.println(f'waiting retry tasks: {len(waiting_retry_list)}')
        CopyRetry.println(f'success tasks: {len(success_list)}')
        CopyRetry.println(f'failed tasks: {len(failed_list)}')

        # print task info for debug
        if CopyRetry.PRINT_TASKS:
            for l in copying_list:
                print(f'copying: {l}')
            for l in waiting_list:
                print(f'waiting: {l}')
            for l in waiting_retry_list:
                print(f'waiting retry: {l}')
            for l in success_list:
                print(f'success: {l}')
            for l in failed_list:
                print(f'failed: {l}')

        # If no copying or waiting tasks, retry a task from failed list if any.
        result = True
        if (len(copying_list) + len(waiting_list) + len(waiting_retry_list)) == 0 and len(failed_list) > 0:
            result = False
            for task in failed_list:
                retry_id = task['id']
                if retry_id not in self.retry_dict:
                    self.retry_dict[retry_id] = 0

                if self.retry_dict[retry_id] < CopyRetry.MAX_RETRIES:
                    CopyRetry.println(f'add retry: {retry_id}')
                    sys.stdout.flush()
                    copy_tasklist.retry(retry_id)
                    self.retry_dict[retry_id] += 1
                    result = True
                    break

        return result, (len(copying_list) + len(waiting_list) + len(waiting_retry_list) + len(failed_list)) == 0

    def retry(self) -> int:
        result, finished = self._check()
        while result and not finished:
            time.sleep(1 * 60)
            result, finished = self._check()

        return 0 if result else 1


if __name__ == '__main__':
    sys.exit(CopyRetry().retry())
